#include "vzconn/pool/perfectbufferpool.h"

namespace vzconn {

PerfectBufferPool *PerfectBufferPool::pool_instance_ = NULL;

PerfectBufferPool *PerfectBufferPool::Instance() {
  if(!pool_instance_) {
    pool_instance_ = new PerfectBufferPool();
  }
  return pool_instance_;
}

PerfectBufferPool::PerfectBufferPool() {
}

PerfectBufferPool::~PerfectBufferPool() {
}

ByteBuffer::Ptr PerfectBufferPool::TakeBuffer(std::size_t mini_size) {
  boost::mutex::scoped_lock buffer_mutex(pool_mutex_);
  if(buffers_.size() == 0) {
    return ByteBuffer::Ptr(new ByteBuffer());
  }
  return TaskPerfectBuffer(mini_size);
}

void PerfectBufferPool::RecyleBuffer(ByteBuffer::Ptr buffer) {
  boost::mutex::scoped_lock buffer_mutex(pool_mutex_);
  InsertBuffer(buffer);
}

ByteBuffer::Ptr PerfectBufferPool::TaskPerfectBuffer(std::size_t mini_size) {
  BOOST_ASSERT(buffers_.size() > 0);
  // Small -> Big
  ByteBuffer::Ptr perfect_buffer;
  for(Buffers::iterator iter = buffers_.begin();
      iter != buffers_.end(); ++iter) {
    if((*iter)->Capacity() >= mini_size) {
      perfect_buffer = *iter;
      buffers_.erase(iter);
      return perfect_buffer;
    }
  }
  perfect_buffer = buffers_.back();
  buffers_.pop_back();
  return perfect_buffer;
}

void PerfectBufferPool::InsertBuffer(ByteBuffer::Ptr buffer) {
  for(Buffers::iterator iter = buffers_.begin();
      iter != buffers_.end(); ++iter) {
    if((*iter)->Capacity() > buffer->Capacity()) {
      buffers_.insert(iter, buffer);
      return;
    }
  }
  buffers_.push_back(buffer);
}

}